﻿using System;
using System.Collections.Generic;
using Assist;
using Autodesk.Revit.DB;
using YArchitech.Revit;
using HYRevitCode.CurveUtility;
using HYRevitCode.XYZUtility;

namespace YJKRGeometry.CurveUtility
{
	public static class CurveUtility
	{
		public static List<Curve> SplitOneCurve(Curve inputCurve, double useLength)
		{
			return CurveUtilityMethod.SplitOneCurve(inputCurve, useLength);
		}

		public static Curve TransformCurveAtZAixs(Curve inputCurve, double moveZValue, bool ifAbsolute = true)
		{
			return CurveUtilityMethod.TransformCurveAtZAixs(inputCurve, moveZValue, ifAbsolute);
		}

		public static bool IsCurveCrossWall(Curve curve, Element ele, RevitLinkInstance inputLinkInstance, Transform inputTransForm)
		{
			Wall wall = ele as Wall;
			LocationCurve locationCurve = wall.Location as LocationCurve;
			if (wall == null)
			{
				return false;
			}
			Curve curve2;
			if (inputLinkInstance == null)
			{
				curve2 = locationCurve.Curve;
			}
			else
			{
				curve2 = locationCurve.Curve;
				if (inputTransForm != null)
				{
					curve2 = curve2.CreateTransformed(inputTransForm);
				}
			}
			double width = wall.WallType.Width;
			return CurveUtility.IsCurvCrossCurve(curve, curve2, width);
		}

		public static bool IsCurvCrossCurve(Curve curve, Curve curveCurWall, double offestValue)
		{
			Line line = curve as Line;
			Line line2 = curveCurWall as Line;
			if (line != null && line2 == null)
			{
				return false;
			}
			if (line == null && line2 != null)
			{
				return false;
			}
			if (!CurveAssistFunc.IsParallel(curve, curveCurWall))
			{
				return false;
			}
			if (CurveUtility.GetTwoCurvesCrossSeg(curveCurWall, curve) != null)
			{
				return true;
			}
			XYZ pt;
			if (line != null)
			{
				pt = Geometry.CalculatMidPoint(line);
				Geometry.CalculatMidPoint(line2);
			}
			else
			{
				pt = Geometry.CalculatMidPoint(curve as Arc);
				Geometry.CalculatMidPoint(curveCurWall as Arc);
			}
			double num = offestValue / 2.0;
			Curve curve2 = CurveUtility.CreateOffsetCurve(curveCurWall, num);
			Curve curve3 = CurveUtility.CreateOffsetCurve(curveCurWall, -num);
			Line item = Line.CreateBound(curve2.GetEndPoint(0), curve3.GetEndPoint(0));
			Line item2 = Line.CreateBound(curve2.GetEndPoint(1), curve3.GetEndPoint(1));
			List<Curve> list = new List<Curve>();
			list.Add(curve2);
			list.Add(curve3);
			list.Add(item);
			list.Add(item2);
			XYZ hyendPoint = curve.GetEndPoint(0);
			XYZ hyendPoint2 = curve.GetEndPoint(1);
			bool flag = CurveUtility.IsPointInArea(list, hyendPoint);
			bool flag2 = CurveUtility.IsPointInArea(list, hyendPoint2);
			return flag || flag2 || CurveUtility.IsPointInArea(list, pt);
		}

		public static Curve CreateOffsetCurve(Curve curve, double dOffsetDist)
		{
			return CurveUtilityMethod.CreateOffsetCurve(curve, dOffsetDist);
		}

		public static bool IsPointInArea(List<Curve> area, XYZ pt)
		{
			return XYZUtilityMethod.IsPointInArea(area, pt);
		}

		public static List<Curve> GetCrossSideSegFromAreas(List<Area> lstArea)
		{
			List<Curve> list = new List<Curve>();
			list.Clear();
			foreach (Area area in lstArea)
			{
				foreach (IList<BoundarySegment> list2 in area.GetBoundarySegments(new SpatialElementBoundaryOptions()))
				{
					foreach (BoundarySegment segment in list2)
					{
						list.Add(segment.GetCurve());
					}
				}
			}
			return CurveUtility.GetCrossSideSegFromCurves(list);
		}

		public static List<Curve> GetCrossSideSegFromCurves(List<Curve> lstTolCurves)
		{
			List<Curve> list = new List<Curve>();
			for (int i = 0; i < lstTolCurves.Count - 1; i++)
			{
				Curve curveOne = lstTolCurves[i];
				for (int j = i + 1; j < lstTolCurves.Count; j++)
				{
					Curve curveTwo = lstTolCurves[j];
					Curve twoCurvesCrossSeg = CurveUtility.GetTwoCurvesCrossSeg(curveOne, curveTwo);
					if (!(twoCurvesCrossSeg == null))
					{
						list.Add(twoCurvesCrossSeg);
					}
				}
			}
			return list;
		}

		public static Curve GetTwoCurvesCrossSeg(Curve curveOne, Curve curveTwo)
		{
			XYZ hyendPoint = curveOne.GetEndPoint(0);
			XYZ hyendPoint2 = curveOne.GetEndPoint(1);
			XYZ xyz = curveTwo.GetEndPoint(0);
			XYZ xyz2 = curveTwo.GetEndPoint(1);
			double num = 0.001;
			if (hyendPoint.DistanceTo(hyendPoint2) < num || xyz.DistanceTo(xyz2) < num)
			{
				return null;
			}
            if ((int)curveOne.Intersect(curveTwo) != 64)
			{
				return null;
			}
			List<XYZ> list = new List<XYZ>();
			List<XYZ> list2 = new List<XYZ>();
			list.Add(hyendPoint);
			list.Add(hyendPoint2);
			list2.Add(xyz);
			list2.Add(xyz2);
			int num2 = 0;
			for (int i = 0; i < list.Count; i++)
			{
				XYZ xyz3 = list[i];
				for (int j = 0; j < list2.Count; j++)
				{
					XYZ xyz4 = list2[j];
					if (xyz3.IsAlmostEqualTo(xyz4, 0.001))
					{
						num2++;
					}
				}
			}
			if (num2 == 2)
			{
				return curveOne.Clone();
			}
			if (num2 == 1)
			{
				if (curveOne.Length < curveTwo.Length)
				{
					return curveOne.Clone();
				}
				if (curveOne.Length > curveTwo.Length)
				{
					return curveTwo.Clone();
				}
			}
			if (curveOne as Line != null)
			{
				List<XYZ> list3 = list;
				list3.Add(list2[0]);
				list3.Add(list2[1]);
				XYZ xyz5 = (hyendPoint2 - hyendPoint).Normalize();
				XYZ xyz6 = list3[0];
				List<double> list4 = new List<double>();
				list4.Add(0.0);
				for (int k = 1; k < list3.Count; k++)
				{
					XYZ xyz7 = list3[k] - xyz6;
					double num3 = xyz7.GetLength();
					if (!xyz7.Normalize().IsAlmostEqualTo(xyz5))
					{
						num3 *= -1.0;
					}
					list4.Add(num3);
				}
				list4.Sort();
				XYZ xyz8 = xyz6 + xyz5 * list4[1];
				XYZ xyz9 = xyz6 + xyz5 * list4[2];
				try
				{
					return Line.CreateBound(xyz8, xyz9);
				}
				catch (Exception)
				{
					return null;
				}
			}
			Arc arc = curveOne as Arc;
			Arc arc2 = curveTwo as Arc;
			if (arc == null)
			{
				return arc;
			}
			XYZ center = arc.Center;
			double radius = arc.Radius;
			XYZ normal = arc.Normal;
			XYZ normal2 = arc2.Normal;
			if (!normal.IsAlmostEqualTo(normal2))
			{
				XYZ xyz10 = xyz2;
				xyz2 = xyz;
				xyz = xyz10;
			}
			XYZ xyz11 = null;
			XYZ xyz12 = null;
			double num4 = arc.Distance(xyz2);
			double num5 = arc.Distance(xyz);
			if (num4 < num5)
			{
				xyz11 = xyz2;
			}
			else
			{
				xyz12 = xyz;
			}
			num4 = arc2.Distance(hyendPoint2);
			num5 = arc2.Distance(hyendPoint);
			if (num4 < num5)
			{
				xyz11 = hyendPoint2;
			}
			else
			{
				xyz12 = hyendPoint;
			}
			if (xyz12 == null || xyz11 == null)
			{
				return null;
			}
			double num6 = arc.XDirection.AngleOnPlaneTo(xyz11 - center, normal);
			double num7 = arc.XDirection.AngleOnPlaneTo(xyz12 - center, normal);
			if (num6 > Math.PI*2)
			{
				num6 -= Math.PI*2;
			}
			if (num7 > Math.PI*2)
			{
				num7 -= Math.PI*2;
			}
			if (num6 > num7)
			{
				num7 += Math.PI*2;
			}
			Curve result;
			try
			{
				result = Arc.Create(center, radius, num6, num7, arc.XDirection, arc.YDirection);
			}
			catch (Exception)
			{
				result = null;
			}
			return result;
		}

		public static bool IsPointInCurve(Curve curve, XYZ point, bool ifUnBound = true)
		{
			return XYZUtilityMethod.IsPointInCurve(curve, point, ifUnBound);
		}
	}
}
